﻿

namespace KillmailFeedUpdater
{
    using System;
    using System.Collections.Generic;
    using System.Data.SqlClient;
    using System.Diagnostics;
    using System.IO;
    using System.Linq;
    using System.Net;
    using System.Threading;
    using System.Xml.XPath;
    using EveKillboard.Core;
    using EveKillboard.Core.Services;
    using EveKillboard.Data;

    class Program
    {
        private static readonly XPathExpression _xpath = XPathExpression.Compile("/eveapi/result/rowset/row[@killID > 0]");

        static void Main(string[] args)
        {
            Trace.Listeners.Clear();
            Trace.Listeners.Add(new ConsoleTraceListener(){ TraceOutputOptions = TraceOptions.None });
            Trace.Listeners.Add(new TextWriterTraceListener(".\\output.log"));
            Trace.AutoFlush = true;

            int delay = 1;
            int interval = 1;

            if (args != null && args.Any())
            {
                if (int.TryParse(args[0], out delay))
                {
                    Console.WriteLine("Delay : {0} hours", delay);
                }
                if (int.TryParse(args[1], out interval))
                {
                    Console.WriteLine("Interval : {0} minutes", interval);
                }
            }


            var feeds = LoadFeeds();
            if (!feeds.Any()) return;
            
            while (!Console.KeyAvailable)
            {
                Console.Clear();
                Console.WriteLine("Delay : {0} hours", delay);
                Console.WriteLine("Interval : {0} minutes", interval);
                Console.WriteLine("Press a key to exit");

                Loop(feeds, delay * -1);
                GC.Collect();
                
                if(Console.KeyAvailable) break;
                Thread.Sleep(TimeSpan.FromMinutes(interval));
            }
        }

        static void Loop(IEnumerable<Feed> feeds, int delay)
        {
            foreach (var feed in feeds)
            {
                //var startDate = new DateTime(1970, 1, 1, 0, 0, 0, 0);
                //var ts = DateTime.UtcNow.AddHours(delay).Subtract(startDate);

                var uri = string.Format("{0}&{1}={2}{3}", feed.Url, feed.Parameters[0].Name, DateTime.UtcNow.AddHours(delay).ToUnixDateTime(), feed.Name == "Eve kill" ? "&alliance=1900696668&alliance=499005583" : null);
                Console.WriteLine(uri);

                try
                {
                    var request = WebRequest.Create(uri) as HttpWebRequest;
                    if (request == null) return;
                    request.KeepAlive = false;
                    request.Timeout = 5000;
                    var response = request.GetResponse() as HttpWebResponse;
                    if (response == null || response.StatusCode != HttpStatusCode.OK)
                    {
                        Trace.WriteLine(string.Format("No response or invalid http status from \"{0}\"", uri));
                        if (response != null)
                            response.Close();
                        continue;
                    }

                    using (var st = response.GetResponseStream())
                        ParseXmlFile(st);
                    response.Close();
                }
                catch (Exception exp)
                {
                    Trace.WriteLine(string.Format("\"{0}\" : Exception : {1}. Details : {2}",uri,exp.GetType(), exp.Message));
                }
            }
        }
        
        static void ParseXmlFile(Stream stream)
        {
            
            using (var parser = new EveKillboard.Core.Parsers.KillmailXmlParser(new EvePriceServicesProvider()))
            using (var dap = new DataAccessProvider(true))
            {
                try
                {
                    var kills = new XPathDocument(stream).CreateNavigator().Select(_xpath);
                    
                    int count = 0;
                    while (kills.MoveNext())
                    {
                        if (kills.Current != null)
                            try
                            {
                                count++;
                                parser.Parse(kills.Current.OuterXml, dap);
                            }
                            catch (Exception exp)
                            {
                                Trace.WriteLine(string.Format("{0} : {1}.\r\nSource:\r\n{2}", exp.GetType().Name, exp.Message, kills.Current.OuterXml));
                            }
                    }
                    Console.WriteLine("Killmails processed : " + count);
                }
                catch (Exception exp)
                {
                    string message = exp.Message;
                    var ex = exp;
                    if (exp.InnerException != null)
                    {
                        ex = exp.InnerException;
                        while (ex.InnerException != null)
                            ex = ex.InnerException;

                        message = ex.Message;
                    }
                    Trace.WriteLine(string.Format("{0} : {1}", ex.GetType().Name, message));
                }
            }
        }
        
        static IEnumerable<Feed> LoadFeeds()
        {
            var feeds = new List<Feed>();

            using (var cnn = new SqlConnection(@"data source=(local)\sql2008;initial catalog=ekb;Integrated Security=SSPI;"))
            using (var cmd = cnn.CreateCommand())
            {


                try
                {
                    cnn.Open();
                    cmd.CommandText = "SELECT ID, Name, Url from KillmailFeeds where IsActive = 1";
                    using (var reader = cmd.ExecuteReader())
                    {
                        while (reader.Read())
                            feeds.Add(new Feed() { Id = reader.GetInt32(0), Name = reader.GetString(1), Url = reader.GetString(2), Parameters = new List<FeedParameter>() });
                    }


                    using (var enu = feeds.GetEnumerator())
                        while (enu.MoveNext())
                        {
                            if (enu.Current == null) continue;

                            cmd.CommandText =
                                string.Format(@"select 
                                      P.Name
                                     ,P.IsStatic
                                     ,T.Name
                                     ,P.StaticValue
                                    from  KillmailFeeds  F
                                    inner join FeedParameters P on P.FeedID = F.ID
                                    inner join FeedParameterValueTypes T on P.TypeID = T.ID
                                    where F.ID = {0}", enu.Current.Id);

                            using (var reader = cmd.ExecuteReader())
                                while (reader.Read())
                                {
                                    enu.Current.Parameters.Add(new FeedParameter()
                                    {
                                        Name = reader.GetString(0),
                                        IsStatic = reader.GetBoolean(1),
                                        Type = reader.GetString(2),
                                        StaticValue = reader.IsDBNull(3) ? null : reader.GetString(3)
                                    });
                                }

                        }

                    cnn.Close();
                }
                catch (Exception)
                {
                    return feeds;
                }
            }
            return feeds;
        }

        internal class Feed
        {
            public int Id { get; set; }
            public string Name { get; set; }
            public List<FeedParameter> Parameters { get; set; }
            public string Url { get; set; }
        }

        internal class FeedParameter
        {
            public string Name { get; set; }
            public bool IsStatic { get; set; }
            public string StaticValue { get; set; }
            public string Type { get; set; }
        }

    }
}
